#include "FlashModule.h"
#include <string.h>

Flash_Def flash1_obj;

rt_err_t W25q_Init(void) {
  if (STATU_GET_NOT(spi3_obj.spi_status, SPI_INITED)) {
    Init_Spi3_Obj();
  }

  flash1_obj.cs_port = GPIO_PORT_B;
  flash1_obj.cs_pin = GPIO_PIN_15;
  flash1_obj.spi_obj = &spi3_obj;
  flash1_obj.sr1 = 0x00;
  flash1_obj.sr2 = 0x00;
  flash1_obj.sr3 = 0x00;
  rt_mutex_init(&(flash1_obj.flash_busy), "flash1 busy mutex", RT_IPC_FLAG_PRIO);

  // 检查flash1状态，设置硬件写保护
  if (W25q_Write_enable(&flash1_obj) == RT_EOK) {
    rt_kprintf("flash1 write enable success\n");
  } else {
    rt_kprintf("flash1 write enable faild\n");
  }
  if (W25q_Read_SRX(&flash1_obj) == RT_EOK) {
    rt_kprintf("get sr1 2 3 data: 0x%02X, 0x%02X, 0x%02X\n", flash1_obj.sr1, flash1_obj.sr2, flash1_obj.sr3);
  } else {
    rt_kprintf("read sr reg faild\n");
  }
  if (W25q_Write_Hw_Enable(&flash1_obj) == RT_EOK) {
    rt_kprintf("set sr hardware write enable reg successful\n");
  } else {
    rt_kprintf("set sr hardware write enable reg faild\n");
  }
  rt_thread_mdelay(8);
  if (W25q_Read_SRX(&flash1_obj) == RT_EOK) {
    rt_kprintf("get sr1 2 3 data: 0x%02X, 0x%02X, 0x%02X\n", flash1_obj.sr1, flash1_obj.sr2, flash1_obj.sr3);
  } else {
    rt_kprintf("read sr reg faild\n");
  }
  // 检查flash1状态，设置硬件写保护

  return RT_EOK;
}

// 擦除1K的页面
rt_err_t W25q_Erase_1K(Flash_Def *obj, uint64_t page_addr) {
  if (STATU_GET_NOT(obj->spi_obj->spi_status, SPI_INITED)) {
    return RT_ERROR;
  }

  // 锁定资源
  uint32_t try_times = 0;
  while (rt_mutex_take(&(obj->flash_busy), 500) != RT_EOK) {
    if (try_times > 8) {
      return RT_EFULL;
    }
    rt_thread_mdelay(2 ^ try_times);
    try_times++;
  }

  // 检查忙碌和写使能状态
  try_times = 0;
  for (;;) {
    if (W25q_Read_SR1(obj) != RT_EOK) {
      // 读不到说明SPI没回复。大概率是因为没写使能。
      //rt_kprintf("get sr1 faild\n");
      if (try_times == 0) {
        if (W25q_Write_enable(obj) != RT_EOK) {
          rt_kprintf("flash1 write enable faild\n");
        }
      }
      try_times++;
      rt_thread_yield();
      rt_hw_us_delay(10);
      continue;
    }
    if (STATU_GET(obj->sr1, 0x03)) {
      // 如果是X3,说明上次写入没完成，啥也不用干
      try_times++;
      rt_thread_yield();
      rt_hw_us_delay(10);
      continue;
    } else if (((obj->sr1 & 0x0F) == 0x00) && STATU_GET_NOT(obj->flash_status, FLASH_WRITEABLE)) {
      // 如果是X0, 说明写完了但是没写使能
      if (W25q_Write_enable(obj) != RT_EOK) {
        rt_kprintf("flash1 write enable faild\n");
      }
      try_times++;
      rt_thread_yield();
      continue;
    } else if (((obj->sr1 & 0x0F) == 0x00) && STATU_GET(obj->flash_status, FLASH_WRITEABLE)) {
      // 如果是X0, 说明写完了但是没写使能
      //rt_kprintf("wait for write able\n");
      try_times++;
      rt_thread_yield();
      rt_hw_us_delay(10);
      continue;
    } else if (STATU_GET(obj->sr1, 0x02)) {
      // 对于X2，则是正常的写使能状态。正常向后执行
      break;
    } else if (try_times > 30000) {
      // 实验次数太多说明状态有问题。直接退出。
      // 释放资源
      rt_mutex_release(&(obj->flash_busy));
      rt_thread_yield();
      return RT_EBUSY;
    } else {
      // 对于0x01这个状态，几乎不存在。
      try_times++;
      rt_thread_yield();
      rt_hw_us_delay(10);
      continue;
    }
  }// 检查忙碌和写使能状态

  rt_err_t res_flag = RT_EOK;
  rt_memset(obj->spi_obj->spi_tx_buf, 0, SPI3_TX_BUF_LEN);
  rt_memset(obj->spi_obj->spi_rx_buf, 0, SPI3_RX_BUF_LEN);

  GPIO_ResetPins(obj->cs_port, obj->cs_pin);

  obj->spi_obj->spi_tx_size = 4;
  obj->spi_obj->spi_tx_buf[0] = 0x82;
  obj->spi_obj->spi_tx_buf[1] = (page_addr / 0x10000) % 0x100;
  obj->spi_obj->spi_tx_buf[2] = (page_addr / 0x100) % 0x100;
  obj->spi_obj->spi_tx_buf[3] = page_addr % 0x100;
  // 读长度，擦除不需要读回
  obj->spi_obj->spi_rx_size = 0;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);

  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);
  // 清零写保护
  STATU_RESET(obj->flash_status, FLASH_WRITEABLE);

  // 临时解决方案，忙碌标志位不管用
  //rt_thread_mdelay(8);

  // 释放资源
  rt_mutex_release(&(obj->flash_busy));
  return res_flag;
}// 擦除1K的页面

// 按字节写入。暂时没做切页
rt_err_t W25q_Write_Pages(Flash_Def *obj, uint64_t page_addr, uint8_t *data_buf, size_t data_len) {
  if (STATU_GET_NOT(obj->spi_obj->spi_status, SPI_INITED)) {
    return RT_ERROR;
  }
  // 不合法的传入
  if (NULL == data_buf) {
    return RT_EINVAL;
  }
  // 锁定资源
  uint32_t try_times = 0;
  while (rt_mutex_take(&(obj->flash_busy), 500) != RT_EOK) {
    if (try_times > 8) {
      return RT_EFULL;
    }
    rt_thread_mdelay(2 ^ try_times);
    try_times++;
  }

  // 检查忙碌和写使能状态
  try_times = 0;
  for (;;) {
    if (W25q_Read_SR1(obj) != RT_EOK) {
      // 读不到说明SPI没回复。大概率是因为没写使能。
      //rt_kprintf("get sr1 faild\n");
      if (try_times == 0) {
        if (W25q_Write_enable(obj) != RT_EOK) {
          rt_kprintf("flash1 write enable faild\n");
        }
      }
      try_times++;
      rt_thread_yield();
      rt_hw_us_delay(10);
      continue;
    }
    if (STATU_GET(obj->sr1, 0x03)) {
      // 如果是X3,说明上次写入没完成，啥也不用干
      try_times++;
      rt_thread_yield();
      rt_hw_us_delay(10);
      continue;
    } else if (((obj->sr1 & 0x0F) == 0x00) && STATU_GET_NOT(obj->flash_status, FLASH_WRITEABLE)) {
      // 如果是X0, 说明写完了但是没写使能
      if (W25q_Write_enable(obj) != RT_EOK) {
        rt_kprintf("flash1 write enable faild\n");
      }
      try_times++;
      rt_thread_yield();
      continue;
    } else if (((obj->sr1 & 0x0F) == 0x00) && STATU_GET(obj->flash_status, FLASH_WRITEABLE)) {
      // 如果是X0, 说明写完了但是没写使能
      try_times++;
      rt_thread_yield();
      rt_hw_us_delay(10);
      continue;
    } else if (STATU_GET(obj->sr1, 0x02)) {
      // 对于X2，则是正常的写使能状态。正常向后执行
      break;
    } else if (try_times > 30000) {
      // 实验次数太多说明状态有问题。直接退出。
      // 释放资源
      rt_mutex_release(&(obj->flash_busy));
      rt_thread_yield();
      return RT_EBUSY;
    } else {
      // 对于0x01这个状态，几乎不存在。
      try_times++;
      rt_thread_yield();
      rt_hw_us_delay(10);
      continue;
    }
  }// 检查忙碌和写使能状态


  // 开始正式写入
  rt_err_t res_flag = RT_EOK;
  rt_memset(obj->spi_obj->spi_tx_buf, 0, SPI3_TX_BUF_LEN);
  rt_memset(obj->spi_obj->spi_rx_buf, 0, SPI3_RX_BUF_LEN);

  GPIO_ResetPins(obj->cs_port, obj->cs_pin);

  obj->spi_obj->spi_tx_size = 4 + data_len;
  obj->spi_obj->spi_tx_buf[0] = 0x02;
  obj->spi_obj->spi_tx_buf[1] = (page_addr / 0x10000) % 0x100;
  obj->spi_obj->spi_tx_buf[2] = (page_addr / 0x100) % 0x100;
  obj->spi_obj->spi_tx_buf[3] = page_addr % 0x100;
  rt_memcpy(obj->spi_obj->spi_tx_buf + 4, data_buf, data_len);
  // 读长度，写入暂时不需要读回
  obj->spi_obj->spi_rx_size = 0;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);
  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);
  // 清零写保护
  STATU_RESET(obj->flash_status, FLASH_WRITEABLE);

  //  // 临时方案。空开写入时间
  //rt_thread_mdelay(2);

  // 释放资源
  rt_mutex_release(&(obj->flash_busy));
  return res_flag;
}// 按字节写入

// 连续写入
rt_err_t W25q_Write_Continuous(Flash_Def *obj, uint64_t start_addr, uint8_t *data_buf, size_t data_len) {
  size_t page_num = 256 - (start_addr % 256);
  uint32_t sink = 0;
  if (data_len <= page_num) {
    page_num = data_len;//不大于256个字节
  }
  rt_err_t res_flag = RT_EOK;
  while (1) {
    res_flag = W25q_Write_Pages(obj, start_addr + sink, (uint8_t *) data_buf + sink, page_num);
    if (res_flag != RT_EOK) {
      return res_flag;
    }
    sink += page_num;
    if (data_len == sink) {
      break;//写入结束了
    } else {
      if (data_len > 256) {
        page_num = 256;//一次可以写入256个字节
      } else {
        page_num = data_len;//不够256个字节了
      }
    }
  }
  return RT_EOK;
}// 连续写入

// 关闭写保护
rt_err_t W25q_Write_enable(Flash_Def *obj) {
  if (STATU_GET_NOT(obj->spi_obj->spi_status, SPI_INITED)) {
    return RT_ERROR;
  }

  if (STATU_GET(obj->flash_status, FLASH_WRITEABLE)) {
    return RT_EOK;
  }
  // 命令操作不能太快，需要切SPI速度
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV8);

  rt_err_t res_flag = RT_EOK;
  rt_memset(obj->spi_obj->spi_tx_buf, 0, SPI3_TX_BUF_LEN);
  rt_memset(obj->spi_obj->spi_rx_buf, 0, SPI3_RX_BUF_LEN);

  GPIO_ResetPins(obj->cs_port, obj->cs_pin);

  obj->spi_obj->spi_tx_size = 1;
  obj->spi_obj->spi_tx_buf[0] = 0x06;
  // 读长度，写入暂时不需要读回
  obj->spi_obj->spi_rx_size = 0;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);
  if (res_flag == RT_EOK) {
    STATU_SET(obj->flash_status, FLASH_WRITEABLE);
  }

  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);


  {// 检查写保护状态确认被关闭
    rt_err_t try_times = 0;
    while (W25q_Check_Write_Enable(obj) != RT_EOK) {
      if (try_times > 1000) {
        rt_kprintf("wirte enable faild\n");
        return RT_EBUSY;
      }
      try_times++;
    }
  }// 检查写保护状态确认被关闭

  // 操作完命令把SPI速度切回去
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV2);
  return res_flag;
}// 关闭写保护

// 打开写保护
rt_err_t W25q_Write_disable(Flash_Def *obj) {
  if (STATU_GET_NOT(obj->spi_obj->spi_status, SPI_INITED)) {
    return RT_ERROR;
  }

  if (STATU_GET_NOT(obj->flash_status, FLASH_WRITEABLE)) {
    return RT_EOK;
  }
  // 命令操作不能太快，需要切SPI速度
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV8);

  rt_err_t res_flag = RT_EOK;
  rt_memset(obj->spi_obj->spi_tx_buf, 0, SPI3_TX_BUF_LEN);
  rt_memset(obj->spi_obj->spi_rx_buf, 0, SPI3_RX_BUF_LEN);

  GPIO_ResetPins(obj->cs_port, obj->cs_pin);

  obj->spi_obj->spi_tx_size = 1;
  obj->spi_obj->spi_tx_buf[0] = 0x04;
  // 读长度，写入暂时不需要读回
  obj->spi_obj->spi_rx_size = 0;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);
  // 如果写入失败则可能是已经写保护关闭了
  STATU_RESET(obj->flash_status, FLASH_WRITEABLE);

  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);
  // 操作完命令把SPI速度切回去
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV2);
  return res_flag;
}// 打开写保护

// 硬件控制写保护
rt_err_t W25q_Write_Hw_Enable(Flash_Def *obj) {
  if (STATU_GET_NOT(obj->spi_obj->spi_status, SPI_INITED)) {
    return RT_ERROR;
  }

  if (STATU_GET_NOT(obj->flash_status, FLASH_WRITEABLE)) {
    return RT_ERROR;
  }

  if (STATU_GET(obj->sr1, (1 << 7))) {
    return RT_EOK;
  }
  // 命令操作不能太快，需要切SPI速度
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV8);

  rt_err_t res_flag = RT_EOK;
  rt_memset(obj->spi_obj->spi_tx_buf, 0, SPI3_TX_BUF_LEN);
  rt_memset(obj->spi_obj->spi_rx_buf, 0, SPI3_RX_BUF_LEN);

  GPIO_ResetPins(obj->cs_port, obj->cs_pin);

  obj->spi_obj->spi_tx_size = 3;
  obj->spi_obj->spi_tx_buf[0] = 0x01;
  STATU_SET(obj->sr1, (1 << 7));
  obj->spi_obj->spi_tx_buf[1] = obj->sr1;
  obj->spi_obj->spi_tx_buf[2] = obj->sr2;
  // 读长度，写入暂时不需要读回
  obj->spi_obj->spi_rx_size = 0;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);
  if (res_flag == RT_EOK) {
    STATU_SET(obj->flash_status, FLASH_WRITEABLE);
  }

  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);


  {// 检查写保护状态确认被关闭
    rt_err_t try_times = 0;
    while (W25q_Check_Write_Enable(obj) != RT_EOK) {
      if (try_times > 1000) {
        rt_kprintf("wirte enable faild\n");
        return RT_EBUSY;
      }
      try_times++;
    }
  }// 检查写保护状态确认被关闭

  // 操作完命令把SPI速度切回去
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV2);
  return res_flag;
}// 关闭写保护

// 读取任意地址，注意自己把握不要跨页。每页256字节，也就是0x100
rt_err_t W25q_Read_page(Flash_Def *obj, uint64_t page_addr, uint8_t *data_buf, size_t data_len) {
  if (STATU_GET_NOT(obj->spi_obj->spi_status, SPI_INITED)) {
    return RT_ERROR;
  }

  // 先清除状态
  rt_err_t res_flag = RT_EOK;
  rt_memset(obj->spi_obj->spi_tx_buf, 0, SPI3_TX_BUF_LEN);
  rt_memset(obj->spi_obj->spi_rx_buf, 0, SPI3_RX_BUF_LEN);

  // 拉低对应的cs引脚
  GPIO_ResetPins(obj->cs_port, obj->cs_pin);

  // 创建命令
  obj->spi_obj->spi_tx_size = 5;
  obj->spi_obj->spi_tx_buf[0] = 0x0B;
  obj->spi_obj->spi_tx_buf[1] = (page_addr / 0x10000) % 0x100;
  obj->spi_obj->spi_tx_buf[2] = (page_addr / 0x100) % 0x100;
  obj->spi_obj->spi_tx_buf[3] = page_addr % 0x100;
  // 读长度
  obj->spi_obj->spi_rx_size = data_len;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);
  // 如果传输成功，并且设置了读取缓冲区，就从头复制过来，否则自己去spi缓冲区处理
  if (res_flag == RT_EOK && NULL != data_buf) {
    rt_memcpy(data_buf, obj->spi_obj->spi_rx_buf + obj->spi_obj->spi_tx_size, obj->spi_obj->spi_rx_size);
  }

  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);

  return res_flag;
}
// 读取连续地址，不要超过4096，也就是0x1000
uint8_t read_buf[256];
rt_err_t W25q_Read(Flash_Def *obj, uint64_t page_addr, uint8_t *data_buf, size_t data_len) {
  // 锁定资源
  uint32_t try_times = 0;
  while (rt_mutex_take(&(obj->flash_busy), 500) != RT_EOK) {
    if (try_times > 8) {
      return RT_EFULL;
    }
    try_times++;
  }
  // 检查忙碌状态。没擦写完不能进入读取
  try_times = 0;
  while (W25q_Check_Write_Enable(obj) != RT_EOK) {
    if (try_times > 1000) {
      // 释放资源
      rt_mutex_release(&(obj->flash_busy));
      return RT_EBUSY;
    } else if (try_times == 0) {
      W25q_Write_enable(obj);
    }
    rt_thread_mdelay(1);
    try_times++;
  }
  //  if (W25q_Check_Busy(obj) != RT_EOK){
  //	  rt_thread_mdelay(10);
  //  }

  size_t page_num = 256 - (page_addr % 256);
  uint16_t read_sink = 0;
  if (data_len <= page_num) {
    page_num = data_len;//不大于256个字节
  }
  while (1) {
    W25q_Read_page(obj, page_addr + read_sink, (uint8_t *) read_buf, page_num);
    memcpy(data_buf + read_sink, read_buf, page_num);
    read_sink += page_num;
    if (data_len == read_sink) {
      break;//读取结束了
    } else {
      if (data_len > 256) {
        page_num = 256;//一次可以读取256个字节
      } else {
        page_num = data_len;//不够256个字节了
      }
    }
  }

  // 释放资源
  rt_mutex_release(&(obj->flash_busy));
  return RT_EOK;
}

// 读芯片ID
rt_err_t W25q_Read_Uid(Flash_Def *obj, uint8_t *res_buf) {
  if (STATU_GET_NOT(spi3_obj.spi_status, SPI_INITED)) {
    return RT_ERROR;
  }
  //	if ( STATU_GET_NOT(obj->flash_status, FLASH_WRITEABLE) ) {
  //		return RT_EIO;
  //	}
  //	// 命令操作不能太快，需要切SPI速度
  //	Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV8);

  // 先清除状态
  rt_err_t res_flag = RT_EOK;
  rt_memset(obj->spi_obj->spi_tx_buf, 0, SPI3_TX_BUF_LEN);
  rt_memset(obj->spi_obj->spi_rx_buf, 0, SPI3_RX_BUF_LEN);
  // 拉低对应的cs引脚
  GPIO_ResetPins(obj->cs_port, obj->cs_pin);
  // 创建命令
  obj->spi_obj->spi_tx_size = 2;
  obj->spi_obj->spi_tx_buf[0] = 0x9F;
  obj->spi_obj->spi_tx_buf[1] = 0xC4;
  // 读长度
  obj->spi_obj->spi_rx_size = 2;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);

  rt_sprintf((char *) res_buf, "%02X,%02X", obj->spi_obj->spi_rx_buf[obj->spi_obj->spi_tx_size], obj->spi_obj->spi_rx_buf[obj->spi_obj->spi_tx_size + 1]);
  //rt_kprintf("get flash guid: %s\n", res_buf);
  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);
  //	// 操作完命令把SPI速度切回去
  //	Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV2);
  return res_flag;
}// 读芯片ID

// 读状态寄存器
// 注意，即使是读寄存器也需要解除写保护
rt_err_t W25q_Read_SRX(Flash_Def *obj) {
  if (STATU_GET_NOT(spi3_obj.spi_status, SPI_INITED)) {
    return RT_ERROR;
  }
  if (STATU_GET_NOT(obj->flash_status, FLASH_WRITEABLE)) {
    return RT_EIO;
  }
  // 命令操作不能太快，需要切SPI速度
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV8);

  // 先清除状态
  rt_err_t res_flag = RT_EOK;
  rt_memset(obj->spi_obj->spi_tx_buf, 0, SPI3_TX_BUF_LEN);
  rt_memset(obj->spi_obj->spi_rx_buf, 0, SPI3_RX_BUF_LEN);
  // 拉低对应的cs引脚
  GPIO_ResetPins(obj->cs_port, obj->cs_pin);
  // 创建命令
  obj->spi_obj->spi_tx_size = 1;
  obj->spi_obj->spi_tx_buf[0] = 0x05;
  // 读长度
  obj->spi_obj->spi_rx_size = 1;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);
  if (res_flag != RT_EOK) {
    GPIO_SetPins(obj->cs_port, obj->cs_pin);
    return RT_EIO;
  }
  obj->sr1 = obj->spi_obj->spi_rx_buf[1];
  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);
  rt_hw_us_delay(10);
  // 拉低对应的cs引脚
  GPIO_ResetPins(obj->cs_port, obj->cs_pin);
  // 创建命令
  obj->spi_obj->spi_tx_size = 1;
  obj->spi_obj->spi_tx_buf[0] = 0x35;
  // 读长度
  obj->spi_obj->spi_rx_size = 1;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);
  if (res_flag != RT_EOK) {
    GPIO_SetPins(obj->cs_port, obj->cs_pin);
    return RT_EIO;
  }
  obj->sr2 = obj->spi_obj->spi_rx_buf[1];
  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);
  rt_hw_us_delay(10);
  // 拉低对应的cs引脚
  GPIO_ResetPins(obj->cs_port, obj->cs_pin);
  // 创建命令
  obj->spi_obj->spi_tx_size = 1;
  obj->spi_obj->spi_tx_buf[0] = 0x15;
  // 读长度
  obj->spi_obj->spi_rx_size = 1;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);
  if (res_flag != RT_EOK) {
    GPIO_SetPins(obj->cs_port, obj->cs_pin);
    return RT_EIO;
  }
  obj->sr3 = obj->spi_obj->spi_rx_buf[1];
  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);
  // 操作完命令把SPI速度切回去
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV2);
  return res_flag;
}// 读状态寄存器

// 更新寄存器SR1状态。最好启动了硬件写保护使用。否则光读SR寄存器就要判断很多写保护状态s
rt_err_t W25q_Read_SR1(Flash_Def *obj) {
  if (STATU_GET_NOT(spi3_obj.spi_status, SPI_INITED)) {
    return RT_ERROR;
  }
  // 命令操作不能太快，需要切SPI速度
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV8);

  // 先清除状态
  rt_err_t res_flag = RT_EOK;
  rt_memset(obj->spi_obj->spi_tx_buf, 0, SPI3_TX_BUF_LEN);
  rt_memset(obj->spi_obj->spi_rx_buf, 0, SPI3_RX_BUF_LEN);
  // 拉低对应的cs引脚
  GPIO_ResetPins(obj->cs_port, obj->cs_pin);
  // 创建命令
  obj->spi_obj->spi_tx_size = 1;
  obj->spi_obj->spi_tx_buf[0] = 0x05;
  // 读长度
  obj->spi_obj->spi_rx_size = 1;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);
  if (res_flag != RT_EOK) {
    GPIO_SetPins(obj->cs_port, obj->cs_pin);
    return RT_EIO;
  }
  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);
  obj->sr1 = obj->spi_obj->spi_rx_buf[1];

  // 操作完命令把SPI速度切回去
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV2);
  return res_flag;
}// 更新寄存器SR1状态。最好启动了硬件写保护使用。否则光读SR寄存器就要判断很多写保护状态s

// 查询动作是否完成。返回RT_EOK则正常。RT_EBUSY则忙碌。其余为错误
// 注意，即使是读寄存器也需要解除写保护
rt_err_t W25q_Check_Busy(Flash_Def *obj) {
  if (STATU_GET_NOT(spi3_obj.spi_status, SPI_INITED)) {
    return RT_ERROR;
  }
  if (STATU_GET_NOT(obj->flash_status, FLASH_WRITEABLE)) {
    return RT_EIO;
  }
  // 命令操作不能太快，需要切SPI速度
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV8);

  // 先清除状态
  rt_err_t res_flag = RT_EOK;
  rt_memset(obj->spi_obj->spi_tx_buf, 0, SPI3_TX_BUF_LEN);
  rt_memset(obj->spi_obj->spi_rx_buf, 0, SPI3_RX_BUF_LEN);
  // 拉低对应的cs引脚
  GPIO_ResetPins(obj->cs_port, obj->cs_pin);
  // 创建命令
  obj->spi_obj->spi_tx_size = 1;
  obj->spi_obj->spi_tx_buf[0] = 0x05;
  // 读长度
  obj->spi_obj->spi_rx_size = 1;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);
  if (res_flag != RT_EOK) {
    GPIO_SetPins(obj->cs_port, obj->cs_pin);
    return RT_EIO;
  }
  rt_kprintf("get busy status: 0x%02X\n", obj->spi_obj->spi_rx_buf[1]);
  // 检查寄存器状态
  if (STATU_GET(obj->spi_obj->spi_rx_buf[1], (1 << 0))) {
    res_flag = RT_EBUSY;
  }
  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);
  // 操作完命令把SPI速度切回去
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV2);
  return res_flag;
}

// 查询写保护是否关闭。返回RT_EOK则已关闭。RT_EBUSY则忙碌。其余为错误
// 注意，即使是读寄存器也需要解除写保护
rt_err_t W25q_Check_Write_Enable(Flash_Def *obj) {
  if (STATU_GET_NOT(spi3_obj.spi_status, SPI_INITED)) {
    return RT_ERROR;
  }
  // 这里不检查wirte able状态。因为本来就是为了同步这个状态位
  // 命令操作不能太快，需要切SPI速度
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV8);

  // 先清除状态
  rt_err_t res_flag = RT_EBUSY;
  rt_memset(obj->spi_obj->spi_tx_buf, 0, SPI3_TX_BUF_LEN);
  rt_memset(obj->spi_obj->spi_rx_buf, 0, SPI3_RX_BUF_LEN);
  // 拉低对应的cs引脚
  GPIO_ResetPins(obj->cs_port, obj->cs_pin);
  // 创建命令
  obj->spi_obj->spi_tx_size = 1;
  obj->spi_obj->spi_tx_buf[0] = 0x05;
  // 读长度
  obj->spi_obj->spi_rx_size = 1;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);
  if (res_flag != RT_EOK) {
    GPIO_SetPins(obj->cs_port, obj->cs_pin);
    // 读不上来大概率是写保护没开
    STATU_RESET(obj->flash_status, FLASH_WRITEABLE);
    return RT_EIO;
  }
  //rt_kprintf("get wirte enable status: 0x%02X\n", obj->spi_obj->spi_rx_buf[1]);
  // 检查寄存器状态
  obj->sr1 = obj->spi_obj->spi_rx_buf[1];
  if (STATU_GET(obj->sr1, (1 << 1))) {
    STATU_SET(obj->flash_status, FLASH_WRITEABLE);
    res_flag = RT_EOK;
  }
  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);
  // 操作完命令把SPI速度切回去
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV2);
  return res_flag;
}

// 查询写保护是否打开。返回RT_EOK则已打开。RT_EBUSY则忙碌。其余为错误
// 注意，即使是读寄存器也需要解除写保护
// 这里是为了检查写入置位是否完成
rt_err_t W25q_Check_Write_Disable(Flash_Def *obj) {
  if (STATU_GET_NOT(spi3_obj.spi_status, SPI_INITED)) {
    return RT_ERROR;
  }
  // 忘了关写使能就关闭一下
  if (STATU_GET_NOT(obj->flash_status, FLASH_WRITEABLE)) {
    W25q_Write_disable(obj);
  }
  // 命令操作不能太快，需要切SPI速度
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV8);

  // 先清除状态
  rt_err_t res_flag = RT_EBUSY;
  rt_memset(obj->spi_obj->spi_tx_buf, 0, SPI3_TX_BUF_LEN);
  rt_memset(obj->spi_obj->spi_rx_buf, 0, SPI3_RX_BUF_LEN);
  // 拉低对应的cs引脚
  GPIO_ResetPins(obj->cs_port, obj->cs_pin);
  // 创建命令
  obj->spi_obj->spi_tx_size = 1;
  obj->spi_obj->spi_tx_buf[0] = 0x05;
  // 读长度
  obj->spi_obj->spi_rx_size = 1;
  // 启动一次交换传输
  res_flag = Spi_Start_Wait(obj->spi_obj);
  // 有可能出现读取失败的情况。这意味着写操作已经被禁止。所以这里不检查读状态是否返回正确

  //rt_kprintf("get wirte disabled status: 0x%02X\n", obj->spi_obj->spi_rx_buf[1]);
  // 检查寄存器状态
  obj->sr1 = obj->spi_obj->spi_rx_buf[1];
  if (STATU_GET_NOT(obj->spi_obj->spi_rx_buf[1], (1 << 1))) {
    STATU_RESET(obj->flash_status, FLASH_WRITEABLE);
    res_flag = RT_EOK;
  } else {
    // 这里特别置为的主要原因是读取成功会改变这个标志位的状态为OK
    STATU_SET(obj->flash_status, FLASH_WRITEABLE);
    res_flag = RT_EBUSY;
  }
  // 重新拉高CS
  GPIO_SetPins(obj->cs_port, obj->cs_pin);
  // 操作完命令把SPI速度切回去
  Spi_Set_Band(obj->spi_obj, SPI_BR_CLK_DIV2);
  return res_flag;
}
